#include "vcd-error.h"

#ifdef USE_FREERDP_ERROR


#define ERRBASE_DEFINE(_code)                                            \
    {                                                                    \
        ERRBASE_##_code, "ERRBASE_" #_code, ERRBASE_##_code##_STRING, "" \
    }

/* Protocol-independent codes */
/* Special codes */
#define ERRBASE_SUCCESS_STRING "Success."
#define ERRBASE_RESTART_STRING "verystream will reconnect."
#define ERRBASE_NONE_STRING ""
static const ERRINFO ERRBASE_CODES[] = { ERRBASE_DEFINE(SUCCESS),
                                         ERRBASE_DEFINE(RESTART),
                                         ERRBASE_DEFINE(NONE) };

const char* freerdp_get_error_base_string(UINT32 code){
    const ERRINFO* errInfo;

        errInfo = &ERRBASE_CODES[0];

        while (errInfo->code != ERRBASE_NONE)
        {
            if (code == errInfo->code)
            {
                return errInfo->info;
            }

            errInfo++;
        }

        return "ERRBASE_UNKNOWN";
}

const char* freerdp_get_error_base_name(UINT32 code){
    const ERRINFO* errInfo;

    errInfo = &ERRBASE_CODES[0];

    while (errInfo->code != ERRBASE_NONE)
    {
        if (code == errInfo->code)
        {
            return errInfo->name;
        }

        errInfo++;
    }

    return "ERRBASE_UNKNOWN";
}

const char* freerdp_get_error_base_category(UINT32 code){
    const ERRINFO* errInfo;

    errInfo = &ERRBASE_CODES[0];

    while (errInfo->code != ERRBASE_NONE)
    {
        if (code == errInfo->code)
        {
            return errInfo->category;
        }

        errInfo++;
    }

    return "ERRBASE_UNKNOWN";
}






#define ERRINFO_DEFINE(_code, category)                                        \
    {                                                                          \
        ERRINFO_##_code, "ERRINFO_" #_code, ERRINFO_##_code##_STRING, category \
    }

/* Protocol-independent codes */

#define ERRINFO_RPC_INITIATED_DISCONNECT_STRING \
    "The disconnection was initiated by an administrative tool on the server in another session."

#define ERRINFO_RPC_INITIATED_LOGOFF_STRING                                                    \
    "The disconnection was due to a forced logoff initiated by an administrative tool on the " \
    "server in another session."

#define ERRINFO_IDLE_TIMEOUT_STRING "The idle session limit timer on the server has elapsed."

#define ERRINFO_LOGON_TIMEOUT_STRING "The active session limit timer on the server has elapsed."

#define ERRINFO_DISCONNECTED_BY_OTHER_CONNECTION_STRING \
    "Another user connected to the server, forcing the disconnection of the current connection."

#define ERRINFO_OUT_OF_MEMORY_STRING "The server ran out of available memory resources."

#define ERRINFO_SERVER_DENIED_CONNECTION_STRING "The server denied the connection."

#define ERRINFO_SERVER_INSUFFICIENT_PRIVILEGES_STRING \
    "The user cannot connect to the server due to insufficient access privileges."

#define ERRINFO_SERVER_FRESH_CREDENTIALS_REQUIRED_STRING                                        \
    "The server does not accept saved user credentials and requires that the user enter their " \
    "credentials for each connection."

#define ERRINFO_RPC_INITIATED_DISCONNECT_BY_USER_STRING                                       \
    "The disconnection was initiated by an administrative tool on the server running in the " \
    "user's session."

#define ERRINFO_LOGOFF_BY_USER_STRING \
    "The disconnection was initiated by the user logging off their session on the server."

#define ERRINFO_CLOSE_STACK_ON_DRIVER_NOT_READY_STRING                                             \
    "The display driver in the remote session did not report any status within the time allotted " \
    "for startup."

#define ERRINFO_SERVER_DWM_CRASH_STRING \
    "The DWM process running in the remote session terminated unexpectedly."

#define ERRINFO_CLOSE_STACK_ON_DRIVER_FAILURE_STRING                                              \
    "The display driver in the remote session was unable to complete all the tasks required for " \
    "startup."

#define ERRINFO_CLOSE_STACK_ON_DRIVER_IFACE_FAILURE_STRING                                   \
    "The display driver in the remote session started up successfully, but due to internal " \
    "failures was not usable by the remoting stack."

#define ERRINFO_SERVER_WINLOGON_CRASH_STRING \
    "The Winlogon process running in the remote session terminated unexpectedly."

#define ERRINFO_SERVER_CSRSS_CRASH_STRING \
    "The CSRSS process running in the remote session terminated unexpectedly."

/* Protocol-independent codes generated by the Connection Broker */

#define ERRINFO_CB_DESTINATION_NOT_FOUND_STRING "The target endpoint could not be found."

#define ERRINFO_CB_LOADING_DESTINATION_STRING                                                \
    "The target endpoint to which the client is being redirected is disconnecting from the " \
    "Connection Broker."

#define ERRINFO_CB_REDIRECTING_TO_DESTINATION_STRING \
    "An error occurred while the connection was being redirected to the target endpoint."

#define ERRINFO_CB_SESSION_ONLINE_VM_WAKE_STRING \
    "An error occurred while the target endpoint (a virtual machine) was being awakened."

#define ERRINFO_CB_SESSION_ONLINE_VM_BOOT_STRING \
    "An error occurred while the target endpoint (a virtual machine) was being started."

#define ERRINFO_CB_SESSION_ONLINE_VM_NO_DNS_STRING \
    "The IP address of the target endpoint (a virtual machine) cannot be determined."

#define ERRINFO_CB_DESTINATION_POOL_NOT_FREE_STRING \
    "There are no available endpoints in the pool managed by the Connection Broker."

#define ERRINFO_CB_CONNECTION_CANCELLED_STRING "Processing of the connection has been cancelled."

#define ERRINFO_CB_CONNECTION_ERROR_INVALID_SETTINGS_STRING                                 \
    "The settings contained in the routingToken field of the X.224 Connection Request PDU " \
    "(section 2.2.1.1) cannot be validated."

#define ERRINFO_CB_SESSION_ONLINE_VM_BOOT_TIMEOUT_STRING \
    "A time-out occurred while the target endpoint (a virtual machine) was being started."

#define ERRINFO_CB_SESSION_ONLINE_VM_SESSMON_FAILED_STRING                                         \
    "A session monitoring error occurred while the target endpoint (a virtual machine) was being " \
    "started."

/* Protocol-independent licensing codes */

#define ERRINFO_LICENSE_INTERNAL_STRING \
    "An internal error has occurred in the Terminal Services licensing component."

#define ERRINFO_LICENSE_NO_LICENSE_SERVER_STRING                                                 \
    "A Remote Desktop License Server (section 1.1) could not be found to provide a " \
    "license."

#define ERRINFO_LICENSE_NO_LICENSE_STRING                                                     \
    "There are no Client Access Licenses (section 1.1) available for the target " \
    "remote computer."

#define ERRINFO_LICENSE_BAD_CLIENT_MSG_STRING \
    "The remote computer received an invalid licensing message from the client."

#define ERRINFO_LICENSE_HWID_DOESNT_MATCH_LICENSE_STRING \
    "The Client Access License (section 1.1) stored by the client has been modified."

#define ERRINFO_LICENSE_BAD_CLIENT_LICENSE_STRING                                                \
    "The Client Access License (section 1.1) stored by the client is in an invalid " \
    "format."

#define ERRINFO_LICENSE_CANT_FINISH_PROTOCOL_STRING                                          \
    "Network problems have caused the licensing protocol (section 1.3.3) to be " \
    "terminated."

#define ERRINFO_LICENSE_CLIENT_ENDED_PROTOCOL_STRING \
    "The client prematurely ended the licensing protocol (section 1.3.3)."

#define ERRINFO_LICENSE_BAD_CLIENT_ENCRYPTION_STRING \
    "A licensing message (sections 2.2 and 5.1) was incorrectly encrypted."

#define ERRINFO_LICENSE_CANT_UPGRADE_LICENSE_STRING                                          \
    "The Client Access License (section 1.1) stored by the client could not be " \
    "upgraded or renewed."

#define ERRINFO_LICENSE_NO_REMOTE_CONNECTIONS_STRING \
    "The remote computer is not licensed to accept remote connections."

/* RDP specific codes */

#define ERRINFO_UNKNOWN_DATA_PDU_TYPE_STRING \
    "Unknown pduType2 field in a received Share Data Header (section 2.2.8.1.1.1.2)."

#define ERRINFO_UNKNOWN_PDU_TYPE_STRING \
    "Unknown pduType field in a received Share Control Header (section 2.2.8.1.1.1.1)."

#define ERRINFO_DATA_PDU_SEQUENCE_STRING \
    "An out-of-sequence Slow-Path Data PDU (section 2.2.8.1.1.1.1) has been received."

#define ERRINFO_CONTROL_PDU_SEQUENCE_STRING \
    "An out-of-sequence Slow-Path Non-Data PDU (section 2.2.8.1.1.1.1) has been received."

#define ERRINFO_INVALID_CONTROL_PDU_ACTION_STRING                                              \
    "A Control PDU (sections 2.2.1.15 and 2.2.1.16) has been received with an invalid action " \
    "field."

#define ERRINFO_INVALID_INPUT_PDU_TYPE_STRING                                                  \
    "(a) A Slow-Path Input Event (section 2.2.8.1.1.3.1.1) has been received with an invalid " \
    "messageType field.\n"                                                                     \
    "(b) A Fast-Path Input Event (section 2.2.8.1.2.2) has been received with an invalid "     \
    "eventCode field."

#define ERRINFO_INVALID_INPUT_PDU_MOUSE_STRING                                               \
    "(a) A Slow-Path Mouse Event (section 2.2.8.1.1.3.1.1.3) or Extended Mouse Event "       \
    "(section 2.2.8.1.1.3.1.1.4) has been received with an invalid pointerFlags field.\n"    \
    "(b) A Fast-Path Mouse Event (section 2.2.8.1.2.2.3) or Fast-Path Extended Mouse Event " \
    "(section 2.2.8.1.2.2.4) has been received with an invalid pointerFlags field."

#define ERRINFO_INVALID_REFRESH_RECT_PDU_STRING \
    "An invalid Refresh Rect PDU (section 2.2.11.2) has been received."

#define ERRINFO_CREATE_USER_DATA_FAILED_STRING                                              \
    "The server failed to construct the GCC Conference Create Response user data (section " \
    "2.2.1.4)."

#define ERRINFO_CONNECT_FAILED_STRING                                                \
    "Processing during the Channel Connection phase of the Connection Sequence " \
    "(see section 1.3.1.1 for an overview of the Connection Sequence phases) has failed."

#define ERRINFO_CONFIRM_ACTIVE_HAS_WRONG_SHAREID_STRING                                       \
    "A Confirm Active PDU (section 2.2.1.13.2) was received from the client with an invalid " \
    "shareId field."

#define ERRINFO_CONFIRM_ACTIVE_HAS_WRONG_ORIGINATOR_STRING                                    \
    "A Confirm Active PDU (section 2.2.1.13.2) was received from the client with an invalid " \
    "originatorId field."

#define ERRINFO_PERSISTENT_KEY_PDU_BAD_LENGTH_STRING \
    "There is not enough data to process a Persistent Key List PDU (section 2.2.1.17)."

#define ERRINFO_PERSISTENT_KEY_PDU_ILLEGAL_FIRST_STRING                                    \
    "A Persistent Key List PDU (section 2.2.1.17) marked as PERSIST_PDU_FIRST (0x01) was " \
    "received after the reception "                                                        \
    "of a prior Persistent Key List PDU also marked as PERSIST_PDU_FIRST."

#define ERRINFO_PERSISTENT_KEY_PDU_TOO_MANY_TOTAL_KEYS_STRING                                      \
    "A Persistent Key List PDU (section 2.2.1.17) was received which specified a total number of " \
    "bitmap cache entries larger than 262144."

#define ERRINFO_PERSISTENT_KEY_PDU_TOO_MANY_CACHE_KEYS_STRING                                     \
    "A Persistent Key List PDU (section 2.2.1.17) was received which specified an invalid total " \
    "number of keys for a bitmap cache "                                                          \
    "(the number of entries that can be stored within each bitmap cache is specified in the "     \
    "Revision 1 or 2 Bitmap Cache Capability Set "                                                \
    "(section 2.2.7.1.4) that is sent from client to server)."

#define ERRINFO_INPUT_PDU_BAD_LENGTH_STRING                                                  \
    "There is not enough data to process Input Event PDU Data (section 2.2.8.1.1.3.1) or a " \
    "Fast-Path Input Event PDU (section 2.2.8.1.2)."

#define ERRINFO_BITMAP_CACHE_ERROR_PDU_BAD_LENGTH_STRING                       \
    "There is not enough data to process the shareDataHeader, NumInfoBlocks, " \
    "Pad1, and Pad2 fields of the Bitmap Cache Error PDU Data (section 2.2.2.3.1.1)."

#define ERRINFO_SECURITY_DATA_TOO_SHORT_STRING                                                    \
    "(a) The dataSignature field of the Fast-Path Input Event PDU (section 2.2.8.1.2) does not "  \
    "contain enough data.\n"                                                                      \
    "(b) The fipsInformation and dataSignature fields of the Fast-Path Input Event PDU (section " \
    "2.2.8.1.2) do not contain enough data."

#define ERRINFO_VCHANNEL_DATA_TOO_SHORT_STRING                                                 \
    "(a) There is not enough data in the Client Network Data (section 2.2.1.3.4) to read the " \
    "virtual channel configuration data.\n"                                                    \
    "(b) There is not enough data to read a complete Channel PDU Header (section 2.2.6.1.1)."

#define ERRINFO_SHARE_DATA_TOO_SHORT_STRING                                                      \
    "(a) There is not enough data to process Control PDU Data (section 2.2.1.15.1).\n"           \
    "(b) There is not enough data to read a complete Share Control Header (section "             \
    "2.2.8.1.1.1.1).\n"                                                                          \
    "(c) There is not enough data to read a complete Share Data Header (section 2.2.8.1.1.1.2) " \
    "of a Slow-Path Data PDU (section 2.2.8.1.1.1.1).\n"                                         \
    "(d) There is not enough data to process Font List PDU Data (section 2.2.1.18.1)."

#define ERRINFO_BAD_SUPPRESS_OUTPUT_PDU_STRING                                                   \
    "(a) There is not enough data to process Suppress Output PDU Data (section 2.2.11.3.1).\n"   \
    "(b) The allowDisplayUpdates field of the Suppress Output PDU Data (section 2.2.11.3.1) is " \
    "invalid."

#define ERRINFO_CONFIRM_ACTIVE_PDU_TOO_SHORT_STRING                                               \
    "(a) There is not enough data to read the shareControlHeader, shareId, originatorId, "        \
    "lengthSourceDescriptor, "                                                                    \
    "and lengthCombinedCapabilities fields of the Confirm Active PDU Data (section "              \
    "2.2.1.13.2.1).\n"                                                                            \
    "(b) There is not enough data to read the sourceDescriptor, numberCapabilities, pad2Octets, " \
    "and capabilitySets "                                                                         \
    "fields of the Confirm Active PDU Data (section 2.2.1.13.2.1)."

#define ERRINFO_CAPABILITY_SET_TOO_SMALL_STRING                                                    \
    "There is not enough data to read the capabilitySetType and the lengthCapability fields in a " \
    "received Capability Set (section 2.2.1.13.1.1.1)."

#define ERRINFO_CAPABILITY_SET_TOO_LARGE_STRING                                            \
    "A Capability Set (section 2.2.1.13.1.1.1) has been received with a lengthCapability " \
    "field that contains a value greater than the total length of the data received."

#define ERRINFO_NO_CURSOR_CACHE_STRING                                                          \
    "(a) Both the colorPointerCacheSize and pointerCacheSize fields in the Pointer Capability " \
    "Set (section 2.2.7.1.5) are set to zero.\n"                                                \
    "(b) The pointerCacheSize field in the Pointer Capability Set (section 2.2.7.1.5) is not "  \
    "present, and the colorPointerCacheSize field is set to zero."

#define ERRINFO_BAD_CAPABILITIES_STRING                                                         \
    "The capabilities received from the client in the Confirm Active PDU (section 2.2.1.13.2) " \
    "were not accepted by the server."

#define ERRINFO_VIRTUAL_CHANNEL_DECOMPRESSION_STRING                                             \
    "An error occurred while using the bulk compressor (section 3.1.8 and section " \
    "3.1.8) to decompress a Virtual Channel PDU (section 2.2.6.1)"

#define ERRINFO_INVALID_VC_COMPRESSION_TYPE_STRING                                             \
    "An invalid bulk compression package was specified in the flags field of the Channel PDU " \
    "Header (section 2.2.6.1.1)."

#define ERRINFO_INVALID_CHANNEL_ID_STRING                                                     \
    "An invalid MCS channel ID was specified in the mcsPdu field of the Virtual Channel PDU " \
    "(section 2.2.6.1)."

#define ERRINFO_VCHANNELS_TOO_MANY_STRING                                                          \
    "The client requested more than the maximum allowed 31 static virtual channels in the Client " \
    "Network Data (section 2.2.1.3.4)."

#define ERRINFO_REMOTEAPP_NOT_ENABLED_STRING                                                      \
    "The INFO_RAIL flag (0x00008000) MUST be set in the flags field of the Info Packet (section " \
    "2.2.1.11.1.1) "                                                                              \
    "as the session on the remote server can only host remote applications."

#define ERRINFO_CACHE_CAP_NOT_SET_STRING                                                  \
    "The client sent a Persistent Key List PDU (section 2.2.1.17) without including the " \
    "prerequisite Revision 2 Bitmap Cache "                                               \
    "Capability Set (section 2.2.7.1.4.2) in the Confirm Active PDU (section 2.2.1.13.2)."

#define ERRINFO_BITMAP_CACHE_ERROR_PDU_BAD_LENGTH2_STRING                                         \
    "The NumInfoBlocks field in the Bitmap Cache Error PDU Data is inconsistent with the amount " \
    "of data in the "                                                                             \
    "Info field (section 2.2.2.3.1.1)."

#define ERRINFO_OFFSCREEN_CACHE_ERROR_PDU_BAD_LENGTH_STRING                                  \
    "There is not enough data to process an Offscreen Bitmap Cache Error PDU  " \
    "section 2.2.2.3.2)."

#define ERRINFO_DRAWNINEGRID_CACHE_ERROR_PDU_BAD_LENGTH_STRING                                  \
    "There is not enough data to process a DrawNineGrid Cache Error PDU (section " \
    "2.2.2.3.3)."

#define ERRINFO_GDIPLUS_PDU_BAD_LENGTH_STRING \
    "There is not enough data to process a GDI+ Error PDU (section 2.2.2.3.4)."

#define ERRINFO_SECURITY_DATA_TOO_SHORT2_STRING \
    "There is not enough data to read a Basic Security Header (section 2.2.8.1.1.2.1)."

#define ERRINFO_SECURITY_DATA_TOO_SHORT3_STRING                                                    \
    "There is not enough data to read a Non-FIPS Security Header (section 2.2.8.1.1.2.2) or FIPS " \
    "Security Header (section 2.2.8.1.1.2.3)."

#define ERRINFO_SECURITY_DATA_TOO_SHORT4_STRING                                                   \
    "There is not enough data to read the basicSecurityHeader and length fields of the Security " \
    "Exchange PDU Data (section 2.2.1.10.1)."

#define ERRINFO_SECURITY_DATA_TOO_SHORT5_STRING                                                    \
    "There is not enough data to read the CodePage, flags, cbDomain, cbUserName, cbPassword, "     \
    "cbAlternateShell, "                                                                           \
    "cbWorkingDir, Domain, UserName, Password, AlternateShell, and WorkingDir fields in the Info " \
    "Packet (section 2.2.1.11.1.1)."

#define ERRINFO_SECURITY_DATA_TOO_SHORT6_STRING                                                \
    "There is not enough data to read the CodePage, flags, cbDomain, cbUserName, cbPassword, " \
    "cbAlternateShell, "                                                                       \
    "and cbWorkingDir fields in the Info Packet (section 2.2.1.11.1.1)."

#define ERRINFO_SECURITY_DATA_TOO_SHORT7_STRING                                                   \
    "There is not enough data to read the clientAddressFamily and cbClientAddress fields in the " \
    "Extended Info Packet (section 2.2.1.11.1.1.1)."

#define ERRINFO_SECURITY_DATA_TOO_SHORT8_STRING                                             \
    "There is not enough data to read the clientAddress field in the Extended Info Packet " \
    "(section 2.2.1.11.1.1.1)."

#define ERRINFO_SECURITY_DATA_TOO_SHORT9_STRING                                                    \
    "There is not enough data to read the cbClientDir field in the Extended Info Packet (section " \
    "2.2.1.11.1.1.1)."

#define ERRINFO_SECURITY_DATA_TOO_SHORT10_STRING                                                 \
    "There is not enough data to read the clientDir field in the Extended Info Packet (section " \
    "2.2.1.11.1.1.1)."

#define ERRINFO_SECURITY_DATA_TOO_SHORT11_STRING                                             \
    "There is not enough data to read the clientTimeZone field in the Extended Info Packet " \
    "(section 2.2.1.11.1.1.1)."

#define ERRINFO_SECURITY_DATA_TOO_SHORT12_STRING                                              \
    "There is not enough data to read the clientSessionId field in the Extended Info Packet " \
    "(section 2.2.1.11.1.1.1)."

#define ERRINFO_SECURITY_DATA_TOO_SHORT13_STRING                                               \
    "There is not enough data to read the performanceFlags field in the Extended Info Packet " \
    "(section 2.2.1.11.1.1.1)."

#define ERRINFO_SECURITY_DATA_TOO_SHORT14_STRING                                                 \
    "There is not enough data to read the cbAutoReconnectLen field in the Extended Info Packet " \
    "(section 2.2.1.11.1.1.1)."

#define ERRINFO_SECURITY_DATA_TOO_SHORT15_STRING                                                  \
    "There is not enough data to read the autoReconnectCookie field in the Extended Info Packet " \
    "(section 2.2.1.11.1.1.1)."

#define ERRINFO_SECURITY_DATA_TOO_SHORT16_STRING                                                  \
    "The cbAutoReconnectLen field in the Extended Info Packet (section 2.2.1.11.1.1.1) contains " \
    "a value "                                                                                    \
    "which is larger than the maximum allowed length of 128 bytes."

#define ERRINFO_SECURITY_DATA_TOO_SHORT17_STRING                                                  \
    "There is not enough data to read the clientAddressFamily and cbClientAddress fields in the " \
    "Extended Info Packet (section 2.2.1.11.1.1.1)."

#define ERRINFO_SECURITY_DATA_TOO_SHORT18_STRING                                            \
    "There is not enough data to read the clientAddress field in the Extended Info Packet " \
    "(section 2.2.1.11.1.1.1)."

#define ERRINFO_SECURITY_DATA_TOO_SHORT19_STRING                                                   \
    "There is not enough data to read the cbClientDir field in the Extended Info Packet (section " \
    "2.2.1.11.1.1.1)."

#define ERRINFO_SECURITY_DATA_TOO_SHORT20_STRING                                                 \
    "There is not enough data to read the clientDir field in the Extended Info Packet (section " \
    "2.2.1.11.1.1.1)."

#define ERRINFO_SECURITY_DATA_TOO_SHORT21_STRING                                             \
    "There is not enough data to read the clientTimeZone field in the Extended Info Packet " \
    "(section 2.2.1.11.1.1.1)."

#define ERRINFO_SECURITY_DATA_TOO_SHORT22_STRING                                              \
    "There is not enough data to read the clientSessionId field in the Extended Info Packet " \
    "(section 2.2.1.11.1.1.1)."

#define ERRINFO_SECURITY_DATA_TOO_SHORT23_STRING \
    "There is not enough data to read the Client Info PDU Data (section 2.2.1.11.1)."

#define ERRINFO_BAD_MONITOR_DATA_STRING \
    "The monitorCount field in the Client Monitor Data (section 2.2.1.3.6) is invalid."

#define ERRINFO_VC_DECOMPRESSED_REASSEMBLE_FAILED_STRING                                        \
    "The server-side decompression buffer is invalid, or the size of the decompressed VC data " \
    "exceeds "                                                                                  \
    "the chunking size specified in the Virtual Channel Capability Set (section 2.2.7.1.10)."

#define ERRINFO_VC_DATA_TOO_LONG_STRING                                                       \
    "The size of a received Virtual Channel PDU (section 2.2.6.1) exceeds the chunking size " \
    "specified "                                                                              \
    "in the Virtual Channel Capability Set (section 2.2.7.1.10)."

#define ERRINFO_BAD_FRAME_ACK_DATA_STRING \
    "There is not enough data to read a TS_FRAME_ACKNOWLEDGE_PDU (section 2.2.3.1)."

#define ERRINFO_GRAPHICS_MODE_NOT_SUPPORTED_STRING \
    "The graphics mode requested by the client is not supported by the server."

#define ERRINFO_GRAPHICS_SUBSYSTEM_RESET_FAILED_STRING \
    "The server-side graphics subsystem failed to reset."

#define ERRINFO_GRAPHICS_SUBSYSTEM_FAILED_STRING                                               \
    "The server-side graphics subsystem is in an error state and unable to continue graphics " \
    "encoding."

#define ERRINFO_TIMEZONE_KEY_NAME_LENGTH_TOO_SHORT_STRING                                          \
    "There is not enough data to read the cbDynamicDSTTimeZoneKeyName field in the Extended Info " \
    "Packet (section 2.2.1.11.1.1.1)."

#define ERRINFO_TIMEZONE_KEY_NAME_LENGTH_TOO_LONG_STRING                                        \
    "The length reported in the cbDynamicDSTTimeZoneKeyName field of the Extended Info Packet " \
    "(section 2.2.1.11.1.1.1) is too long."

#define ERRINFO_DYNAMIC_DST_DISABLED_FIELD_MISSING_STRING                                        \
    "The dynamicDaylightTimeDisabled field is not present in the Extended Info Packet (section " \
    "2.2.1.11.1.1.1)."

#define ERRINFO_VC_DECODING_ERROR_STRING \
    "An error occurred when processing dynamic virtual channel data (section 3.3.5)."

#define ERRINFO_VIRTUALDESKTOPTOOLARGE_STRING                                                 \
    "The width or height of the virtual desktop defined by the monitor layout in the Client " \
    "Monitor Data "                                                                           \
    "(section 2.2.1.3.6) is larger than the maximum allowed value of 32,766."

#define ERRINFO_MONITORGEOMETRYVALIDATIONFAILED_STRING \
    "The monitor geometry defined by the Client Monitor Data (section 2.2.1.3.6) is invalid."

#define ERRINFO_INVALIDMONITORCOUNT_STRING \
    "The monitorCount field in the Client Monitor Data(section 2.2.1.3.6) is too large."

#define ERRINFO_UPDATE_SESSION_KEY_FAILED_STRING                                                   \
    "An attempt to update the session keys while using Standard Security mechanisms (section " \
    "5.3.7) failed."

#define ERRINFO_DECRYPT_FAILED_STRING                                                 \
    "(a) Decryption using Standard Security mechanisms (section 5.3.6) failed.\n" \
    "(b) Session key creation using Standard Security mechanisms (section 5.3.5) failed."

#define ERRINFO_ENCRYPT_FAILED_STRING \
    "Encryption using Standard Security mechanisms (section 5.3.6) failed."

#define ERRINFO_ENCRYPTION_PACKAGE_MISMATCH_STRING                                                 \
    "Failed to find a usable Encryption Method (section 5.3.2) in the encryptionMethods field of " \
    "the Client Security Data (section 2.2.1.4.3)."

#define ERRINFO_DECRYPT_FAILED2_STRING                                                           \
    "Unencrypted data was encountered in a protocol stream which is meant to be encrypted with " \
    "Standard Security mechanisms (section 5.3.6)."

#define ERRINFO_PEER_DISCONNECTED_STRING "The peer connection was lost."

/* Special codes */
#define ERRINFO_SUCCESS_STRING "Success."
#define ERRINFO_NONE_STRING ""

static const ERRINFO ERRINFO_CODES[] = {
    ERRINFO_DEFINE(SUCCESS, CAT_NONE),

    /* Protocol-independent codes */
    ERRINFO_DEFINE(RPC_INITIATED_DISCONNECT, CAT_ADMIN),
    ERRINFO_DEFINE(RPC_INITIATED_LOGOFF, CAT_ADMIN), ERRINFO_DEFINE(IDLE_TIMEOUT, CAT_ADMIN),
    ERRINFO_DEFINE(LOGON_TIMEOUT, CAT_ADMIN),
    ERRINFO_DEFINE(DISCONNECTED_BY_OTHER_CONNECTION, CAT_USE),
    ERRINFO_DEFINE(OUT_OF_MEMORY, CAT_ADMIN), ERRINFO_DEFINE(SERVER_DENIED_CONNECTION, CAT_ADMIN),
    ERRINFO_DEFINE(SERVER_INSUFFICIENT_PRIVILEGES, CAT_ADMIN),
    ERRINFO_DEFINE(SERVER_FRESH_CREDENTIALS_REQUIRED, CAT_ADMIN),
    ERRINFO_DEFINE(RPC_INITIATED_DISCONNECT_BY_USER, CAT_ADMIN),
    ERRINFO_DEFINE(LOGOFF_BY_USER, CAT_USE),
    ERRINFO_DEFINE(CLOSE_STACK_ON_DRIVER_NOT_READY, CAT_SERVER),
    ERRINFO_DEFINE(SERVER_DWM_CRASH, CAT_SERVER),
    ERRINFO_DEFINE(CLOSE_STACK_ON_DRIVER_FAILURE, CAT_SERVER),
    ERRINFO_DEFINE(CLOSE_STACK_ON_DRIVER_IFACE_FAILURE, CAT_SERVER),
    ERRINFO_DEFINE(SERVER_WINLOGON_CRASH, CAT_SERVER),
    ERRINFO_DEFINE(SERVER_CSRSS_CRASH, CAT_SERVER),

    /* Protocol-independent licensing codes */
    ERRINFO_DEFINE(LICENSE_INTERNAL, CAT_LICENSING),
    ERRINFO_DEFINE(LICENSE_NO_LICENSE_SERVER, CAT_LICENSING),
    ERRINFO_DEFINE(LICENSE_NO_LICENSE, CAT_LICENSING),
    ERRINFO_DEFINE(LICENSE_BAD_CLIENT_MSG, CAT_LICENSING),
    ERRINFO_DEFINE(LICENSE_HWID_DOESNT_MATCH_LICENSE, CAT_LICENSING),
    ERRINFO_DEFINE(LICENSE_BAD_CLIENT_LICENSE, CAT_LICENSING),
    ERRINFO_DEFINE(LICENSE_CANT_FINISH_PROTOCOL, CAT_LICENSING),
    ERRINFO_DEFINE(LICENSE_CLIENT_ENDED_PROTOCOL, CAT_LICENSING),
    ERRINFO_DEFINE(LICENSE_BAD_CLIENT_ENCRYPTION, CAT_LICENSING),
    ERRINFO_DEFINE(LICENSE_CANT_UPGRADE_LICENSE, CAT_LICENSING),
    ERRINFO_DEFINE(LICENSE_NO_REMOTE_CONNECTIONS, CAT_LICENSING),

    /* Protocol-independent codes generated by the Connection Broker */
    ERRINFO_DEFINE(CB_DESTINATION_NOT_FOUND, CAT_BROKER),
    ERRINFO_DEFINE(CB_LOADING_DESTINATION, CAT_BROKER),
    ERRINFO_DEFINE(CB_REDIRECTING_TO_DESTINATION, CAT_BROKER),
    ERRINFO_DEFINE(CB_SESSION_ONLINE_VM_WAKE, CAT_BROKER),
    ERRINFO_DEFINE(CB_SESSION_ONLINE_VM_BOOT, CAT_BROKER),
    ERRINFO_DEFINE(CB_SESSION_ONLINE_VM_NO_DNS, CAT_BROKER),
    ERRINFO_DEFINE(CB_DESTINATION_POOL_NOT_FREE, CAT_BROKER),
    ERRINFO_DEFINE(CB_CONNECTION_CANCELLED, CAT_BROKER),
    ERRINFO_DEFINE(CB_CONNECTION_ERROR_INVALID_SETTINGS, CAT_BROKER),
    ERRINFO_DEFINE(CB_SESSION_ONLINE_VM_BOOT_TIMEOUT, CAT_BROKER),
    ERRINFO_DEFINE(CB_SESSION_ONLINE_VM_SESSMON_FAILED, CAT_BROKER),

    /* RDP specific codes */
    ERRINFO_DEFINE(UNKNOWN_DATA_PDU_TYPE, CAT_PROTOCOL),
    ERRINFO_DEFINE(UNKNOWN_PDU_TYPE, CAT_PROTOCOL), ERRINFO_DEFINE(DATA_PDU_SEQUENCE, CAT_PROTOCOL),
    ERRINFO_DEFINE(CONTROL_PDU_SEQUENCE, CAT_PROTOCOL),
    ERRINFO_DEFINE(INVALID_CONTROL_PDU_ACTION, CAT_PROTOCOL),
    ERRINFO_DEFINE(INVALID_INPUT_PDU_TYPE, CAT_PROTOCOL),
    ERRINFO_DEFINE(INVALID_INPUT_PDU_MOUSE, CAT_PROTOCOL),
    ERRINFO_DEFINE(INVALID_REFRESH_RECT_PDU, CAT_PROTOCOL),
    ERRINFO_DEFINE(CREATE_USER_DATA_FAILED, CAT_PROTOCOL), ERRINFO_DEFINE(CONNECT_FAILED, CAT_USE),
    ERRINFO_DEFINE(CONFIRM_ACTIVE_HAS_WRONG_SHAREID, CAT_PROTOCOL),
    ERRINFO_DEFINE(CONFIRM_ACTIVE_HAS_WRONG_ORIGINATOR, CAT_PROTOCOL),
    ERRINFO_DEFINE(PERSISTENT_KEY_PDU_BAD_LENGTH, CAT_PROTOCOL),
    ERRINFO_DEFINE(PERSISTENT_KEY_PDU_ILLEGAL_FIRST, CAT_PROTOCOL),
    ERRINFO_DEFINE(PERSISTENT_KEY_PDU_TOO_MANY_TOTAL_KEYS, CAT_PROTOCOL),
    ERRINFO_DEFINE(PERSISTENT_KEY_PDU_TOO_MANY_CACHE_KEYS, CAT_PROTOCOL),
    ERRINFO_DEFINE(INPUT_PDU_BAD_LENGTH, CAT_PROTOCOL),
    ERRINFO_DEFINE(BITMAP_CACHE_ERROR_PDU_BAD_LENGTH, CAT_PROTOCOL),
    ERRINFO_DEFINE(SECURITY_DATA_TOO_SHORT, CAT_PROTOCOL),
    ERRINFO_DEFINE(VCHANNEL_DATA_TOO_SHORT, CAT_PROTOCOL),
    ERRINFO_DEFINE(SHARE_DATA_TOO_SHORT, CAT_PROTOCOL),
    ERRINFO_DEFINE(BAD_SUPPRESS_OUTPUT_PDU, CAT_PROTOCOL),
    ERRINFO_DEFINE(CONFIRM_ACTIVE_PDU_TOO_SHORT, CAT_PROTOCOL),
    ERRINFO_DEFINE(CAPABILITY_SET_TOO_SMALL, CAT_PROTOCOL),
    ERRINFO_DEFINE(CAPABILITY_SET_TOO_LARGE, CAT_PROTOCOL),
    ERRINFO_DEFINE(NO_CURSOR_CACHE, CAT_PROTOCOL), ERRINFO_DEFINE(BAD_CAPABILITIES, CAT_PROTOCOL),
    ERRINFO_DEFINE(VIRTUAL_CHANNEL_DECOMPRESSION, CAT_PROTOCOL),
    ERRINFO_DEFINE(INVALID_VC_COMPRESSION_TYPE, CAT_PROTOCOL),
    ERRINFO_DEFINE(INVALID_CHANNEL_ID, CAT_PROTOCOL),
    ERRINFO_DEFINE(VCHANNELS_TOO_MANY, CAT_PROTOCOL),
    ERRINFO_DEFINE(REMOTEAPP_NOT_ENABLED, CAT_ADMIN),
    ERRINFO_DEFINE(CACHE_CAP_NOT_SET, CAT_PROTOCOL),
    ERRINFO_DEFINE(BITMAP_CACHE_ERROR_PDU_BAD_LENGTH2, CAT_PROTOCOL),
    ERRINFO_DEFINE(OFFSCREEN_CACHE_ERROR_PDU_BAD_LENGTH, CAT_PROTOCOL),
    ERRINFO_DEFINE(DRAWNINEGRID_CACHE_ERROR_PDU_BAD_LENGTH, CAT_PROTOCOL),
    ERRINFO_DEFINE(GDIPLUS_PDU_BAD_LENGTH, CAT_PROTOCOL),
    ERRINFO_DEFINE(SECURITY_DATA_TOO_SHORT2, CAT_PROTOCOL),
    ERRINFO_DEFINE(SECURITY_DATA_TOO_SHORT3, CAT_PROTOCOL),
    ERRINFO_DEFINE(SECURITY_DATA_TOO_SHORT4, CAT_PROTOCOL),
    ERRINFO_DEFINE(SECURITY_DATA_TOO_SHORT5, CAT_PROTOCOL),
    ERRINFO_DEFINE(SECURITY_DATA_TOO_SHORT6, CAT_PROTOCOL),
    ERRINFO_DEFINE(SECURITY_DATA_TOO_SHORT7, CAT_PROTOCOL),
    ERRINFO_DEFINE(SECURITY_DATA_TOO_SHORT8, CAT_PROTOCOL),
    ERRINFO_DEFINE(SECURITY_DATA_TOO_SHORT9, CAT_PROTOCOL),
    ERRINFO_DEFINE(SECURITY_DATA_TOO_SHORT10, CAT_PROTOCOL),
    ERRINFO_DEFINE(SECURITY_DATA_TOO_SHORT11, CAT_PROTOCOL),
    ERRINFO_DEFINE(SECURITY_DATA_TOO_SHORT12, CAT_PROTOCOL),
    ERRINFO_DEFINE(SECURITY_DATA_TOO_SHORT13, CAT_PROTOCOL),
    ERRINFO_DEFINE(SECURITY_DATA_TOO_SHORT14, CAT_PROTOCOL),
    ERRINFO_DEFINE(SECURITY_DATA_TOO_SHORT15, CAT_PROTOCOL),
    ERRINFO_DEFINE(SECURITY_DATA_TOO_SHORT16, CAT_PROTOCOL),
    ERRINFO_DEFINE(SECURITY_DATA_TOO_SHORT17, CAT_PROTOCOL),
    ERRINFO_DEFINE(SECURITY_DATA_TOO_SHORT18, CAT_PROTOCOL),
    ERRINFO_DEFINE(SECURITY_DATA_TOO_SHORT19, CAT_PROTOCOL),
    ERRINFO_DEFINE(SECURITY_DATA_TOO_SHORT20, CAT_PROTOCOL),
    ERRINFO_DEFINE(SECURITY_DATA_TOO_SHORT21, CAT_PROTOCOL),
    ERRINFO_DEFINE(SECURITY_DATA_TOO_SHORT22, CAT_PROTOCOL),
    ERRINFO_DEFINE(SECURITY_DATA_TOO_SHORT23, CAT_PROTOCOL),
    ERRINFO_DEFINE(BAD_MONITOR_DATA, CAT_PROTOCOL),
    ERRINFO_DEFINE(VC_DECOMPRESSED_REASSEMBLE_FAILED, CAT_PROTOCOL),
    ERRINFO_DEFINE(VC_DATA_TOO_LONG, CAT_PROTOCOL),
    ERRINFO_DEFINE(BAD_FRAME_ACK_DATA, CAT_PROTOCOL),
    ERRINFO_DEFINE(GRAPHICS_MODE_NOT_SUPPORTED, CAT_SERVER),
    ERRINFO_DEFINE(GRAPHICS_SUBSYSTEM_RESET_FAILED, CAT_SERVER),
    ERRINFO_DEFINE(GRAPHICS_SUBSYSTEM_FAILED, CAT_SERVER),
    ERRINFO_DEFINE(TIMEZONE_KEY_NAME_LENGTH_TOO_SHORT, CAT_PROTOCOL),
    ERRINFO_DEFINE(TIMEZONE_KEY_NAME_LENGTH_TOO_LONG, CAT_PROTOCOL),
    ERRINFO_DEFINE(DYNAMIC_DST_DISABLED_FIELD_MISSING, CAT_PROTOCOL),
    ERRINFO_DEFINE(VC_DECODING_ERROR, CAT_PROTOCOL),
    ERRINFO_DEFINE(VIRTUALDESKTOPTOOLARGE, CAT_SERVER),
    ERRINFO_DEFINE(MONITORGEOMETRYVALIDATIONFAILED, CAT_PROTOCOL),
    ERRINFO_DEFINE(INVALIDMONITORCOUNT, CAT_PROTOCOL),
    ERRINFO_DEFINE(UPDATE_SESSION_KEY_FAILED, CAT_PROTOCOL),
    ERRINFO_DEFINE(DECRYPT_FAILED, CAT_PROTOCOL), ERRINFO_DEFINE(ENCRYPT_FAILED, CAT_PROTOCOL),
    ERRINFO_DEFINE(ENCRYPTION_PACKAGE_MISMATCH, CAT_PROTOCOL),
    ERRINFO_DEFINE(DECRYPT_FAILED2, CAT_PROTOCOL), ERRINFO_DEFINE(PEER_DISCONNECTED, CAT_USE),

    ERRINFO_DEFINE(NONE, CAT_NONE)
};
const char* freerdp_get_error_info_string(UINT32 code)
{
    const ERRINFO* errInfo;
    errInfo = &ERRINFO_CODES[0];

    while (errInfo->code != ERRINFO_NONE)
    {
        if (code == errInfo->code)
        {
            return errInfo->info;
        }

        errInfo++;
    }

    return "Unknown error.";
}

const char* freerdp_get_error_info_category(UINT32 code)
{
    const ERRINFO* errInfo;
    errInfo = &ERRINFO_CODES[0];

    while (errInfo->code != ERRINFO_NONE)
    {
        if (code == errInfo->code)
        {
            return errInfo->category;
        }

        errInfo++;
    }

    return "ERRINFO_UNKNOWN";
}

const char* freerdp_get_error_info_name(UINT32 code)
{
    const ERRINFO* errInfo;
    errInfo = &ERRINFO_CODES[0];

    while (errInfo->code != ERRINFO_NONE)
    {
        if (code == errInfo->code)
        {
            return errInfo->name;
        }

        errInfo++;
    }

    return "ERRINFO_UNKNOWN";
}




#define ERRCONNECT_DEFINE(_code, category)                                              \
    {                                                                                   \
        ERRCONNECT_##_code, "ERRCONNECT_" #_code, ERRCONNECT_##_code##_STRING, category \
    }

/* Protocol-independent codes */

#define ERRCONNECT_PRE_CONNECT_FAILED_STRING \
    "A configuration error prevented a connection to be established."

#define ERRCONNECT_CONNECT_UNDEFINED_STRING "A undefined connection error occurred."

#define ERRCONNECT_POST_CONNECT_FAILED_STRING \
    "The connection attempt was aborted due to post connect configuration errors."

#define ERRCONNECT_DNS_ERROR_STRING "The DNS entry could not be resolved."

#define ERRCONNECT_DNS_NAME_NOT_FOUND_STRING "The DNS host name was not found."

#define ERRCONNECT_CONNECT_FAILED_STRING "The connection failed."

#define ERRCONNECT_MCS_CONNECT_INITIAL_ERROR_STRING "The connection failed at initial MCS connect"

#define ERRCONNECT_TLS_CONNECT_FAILED_STRING "The connection failed at TLS connect."

#define ERRCONNECT_AUTHENTICATION_FAILED_STRING "An authentication failure aborted the connection."

#define ERRCONNECT_INSUFFICIENT_PRIVILEGES_STRING \
    "Insufficient privileges to establish a connection."

#define ERRCONNECT_CONNECT_CANCELLED_STRING "The connection was cancelled."

#define ERRCONNECT_SECURITY_NEGO_CONNECT_FAILED_STRING \
    "The connection failed at negotiating security settings."

#define ERRCONNECT_CONNECT_TRANSPORT_FAILED_STRING "The connection transport layer failed."

#define ERRCONNECT_PASSWORD_EXPIRED_STRING "The password has expired and must be changed."

#define ERRCONNECT_PASSWORD_CERTAINLY_EXPIRED_STRING \
    "The password has certainly expired and must be changed."

#define ERRCONNECT_CLIENT_REVOKED_STRING "The client has been revoked."

#define ERRCONNECT_KDC_UNREACHABLE_STRING "The KDC is unreachable."

#define ERRCONNECT_ACCOUNT_DISABLED_STRING "The account is disabled."

#define ERRCONNECT_PASSWORD_MUST_CHANGE_STRING "The password must be changed."

#define ERRCONNECT_LOGON_FAILURE_STRING "Logon failed."

#define ERRCONNECT_WRONG_PASSWORD_STRING "Wrong password supplied."

#define ERRCONNECT_ACCESS_DENIED_STRING "Access denied."

#define ERRCONNECT_ACCOUNT_RESTRICTION_STRING "Account restriction."

#define ERRCONNECT_ACCOUNT_LOCKED_OUT_STRING "Account locked out."

#define ERRCONNECT_ACCOUNT_EXPIRED_STRING "Account expired."

#define ERRCONNECT_LOGON_TYPE_NOT_GRANTED_STRING "Logon type not granted."

#define ERRCONNECT_NO_OR_MISSING_CREDENTIALS_STRING "Credentials invalid or missing."

/* Special codes */
#define ERRCONNECT_SUCCESS_STRING "Success."
#define ERRCONNECT_NONE_STRING ""

static const ERRINFO ERRCONNECT_CODES[] = {
    ERRCONNECT_DEFINE(SUCCESS, CAT_NONE),

    ERRCONNECT_DEFINE(PRE_CONNECT_FAILED, CAT_CONFIG),
    ERRCONNECT_DEFINE(CONNECT_UNDEFINED, CAT_USE),
    ERRCONNECT_DEFINE(POST_CONNECT_FAILED, CAT_CONFIG),
    ERRCONNECT_DEFINE(DNS_ERROR, CAT_USE),
    ERRCONNECT_DEFINE(DNS_NAME_NOT_FOUND, CAT_CONFIG),
    ERRCONNECT_DEFINE(CONNECT_FAILED, CAT_USE),
    ERRCONNECT_DEFINE(MCS_CONNECT_INITIAL_ERROR, CAT_PROTOCOL),
    ERRCONNECT_DEFINE(TLS_CONNECT_FAILED, CAT_USE),
    ERRCONNECT_DEFINE(AUTHENTICATION_FAILED, CAT_USE),
    ERRCONNECT_DEFINE(INSUFFICIENT_PRIVILEGES, CAT_ADMIN),
    ERRCONNECT_DEFINE(CONNECT_CANCELLED, CAT_USE),
    ERRCONNECT_DEFINE(SECURITY_NEGO_CONNECT_FAILED, CAT_USE),
    ERRCONNECT_DEFINE(CONNECT_TRANSPORT_FAILED, CAT_USE),
    ERRCONNECT_DEFINE(PASSWORD_EXPIRED, CAT_ADMIN),
    ERRCONNECT_DEFINE(PASSWORD_CERTAINLY_EXPIRED, CAT_ADMIN),
    ERRCONNECT_DEFINE(CLIENT_REVOKED, CAT_ADMIN),
    ERRCONNECT_DEFINE(KDC_UNREACHABLE, CAT_ADMIN),
    ERRCONNECT_DEFINE(ACCOUNT_DISABLED, CAT_ADMIN),
    ERRCONNECT_DEFINE(PASSWORD_MUST_CHANGE, CAT_ADMIN),
    ERRCONNECT_DEFINE(LOGON_FAILURE, CAT_USE),
    ERRCONNECT_DEFINE(WRONG_PASSWORD, CAT_USE),
    ERRCONNECT_DEFINE(ACCESS_DENIED, CAT_ADMIN),
    ERRCONNECT_DEFINE(ACCOUNT_RESTRICTION, CAT_ADMIN),
    ERRCONNECT_DEFINE(ACCOUNT_LOCKED_OUT, CAT_ADMIN),
    ERRCONNECT_DEFINE(ACCOUNT_EXPIRED, CAT_ADMIN),
    ERRCONNECT_DEFINE(LOGON_TYPE_NOT_GRANTED, CAT_ADMIN),
    ERRCONNECT_DEFINE(NO_OR_MISSING_CREDENTIALS, CAT_USE),

    ERRCONNECT_DEFINE(NONE, CAT_NONE)
};

const char* freerdp_get_error_connect_string(UINT32 code)
{
    const ERRINFO* errInfo;
    errInfo = &ERRCONNECT_CODES[0];

    while (errInfo->code != ERRCONNECT_NONE)
    {
        if (code == errInfo->code)
        {
            return errInfo->info;
        }

        errInfo++;
    }

    return "ERRCONNECT_UNKNOWN";
}

const char* freerdp_get_error_connect_category(UINT32 code)
{
    const ERRINFO* errInfo;
    errInfo = &ERRCONNECT_CODES[0];

    while (errInfo->code != ERRCONNECT_NONE)
    {
        if (code == errInfo->code)
        {
            return errInfo->category;
        }

        errInfo++;
    }

    return "ERRCONNECT_UNKNOWN";
}

const char* freerdp_get_error_connect_name(UINT32 code)
{
    const ERRINFO* errInfo;
    errInfo = &ERRCONNECT_CODES[0];

    while (errInfo->code != ERRCONNECT_NONE)
    {
        if (code == errInfo->code)
        {
            return errInfo->name;
        }

        errInfo++;
    }

    return "ERRCONNECT_UNKNOWN";
}


const char* freerdp_get_last_error_name(UINT32 code)
{
    const char* name = 0;
    const UINT32 cls = GET_FREERDP_ERROR_CLASS(code);
    const UINT32 type = GET_FREERDP_ERROR_TYPE(code);

    switch (cls)
    {
        case FREERDP_ERROR_ERRBASE_CLASS:
            name = freerdp_get_error_base_name(type);
            break;

        case FREERDP_ERROR_ERRINFO_CLASS:
            name = freerdp_get_error_info_name(type);
            break;

        case FREERDP_ERROR_CONNECT_CLASS:
            name = freerdp_get_error_connect_name(type);
            break;

        default:
            name = "rpc error";
            break;
    }

    return name;
}

const char* freerdp_get_last_error_string(UINT32 code)
{
    const char* string = 0;
    const UINT32 cls = GET_FREERDP_ERROR_CLASS(code);
    const UINT32 type = GET_FREERDP_ERROR_TYPE(code);

    switch (cls)
    {
        case FREERDP_ERROR_ERRBASE_CLASS:
            string = freerdp_get_error_base_string(type);
            break;

        case FREERDP_ERROR_ERRINFO_CLASS:
            string = freerdp_get_error_info_string(type);
            break;

        case FREERDP_ERROR_CONNECT_CLASS:
            string = freerdp_get_error_connect_string(type);
            break;

        default:
            string = "rpc error";
            break;
    }

    return string;
}

const char* freerdp_get_last_error_category(UINT32 code)
{
    const char* string = 0;
    const UINT32 cls = GET_FREERDP_ERROR_CLASS(code);
    const UINT32 type = GET_FREERDP_ERROR_TYPE(code);

    switch (cls)
    {
        case FREERDP_ERROR_ERRBASE_CLASS:
            string = freerdp_get_error_base_category(type);
            break;

        case FREERDP_ERROR_ERRINFO_CLASS:
            string = freerdp_get_error_info_category(type);
            break;

        case FREERDP_ERROR_CONNECT_CLASS:
            string = freerdp_get_error_connect_category(type);
            break;

        default:
            string = "rpc error";
            break;
    }

    return string;
}

#ifdef __WIN32__
char* freerdp_get_status_string(int exitCode){
    char* message = NULL;

    if (0x20014 == exitCode) { // ERRCONNECT_LOGON_FAILURE
        message = "用户名或密码错误";
    } else if(0x10005 == exitCode) { // ERRINFO_DISCONNECTED_BY_OTHER_CONNECTION
        message = "有其他用户登录";
    } else if (0x2000D == exitCode || 0x2000C == exitCode) {//虚拟机端口不通或者管理平台串流密码设置错误
        message = "串流配置有误或网络端口不可达";
    }else if(0x1111 == exitCode){
        //message = "重新连接";
        //isReconnect = TRUE;
    }
    else if(0x1110 == exitCode){
        message = "exit by Ctrl+Shift+e";
    }
    return message;
}

int freerdp_get_status_reconnect_status(int exitCode){
    if(exitCode == 0x1111)
        return 1;
    else
        return 0;
}
#else

// xfreerdp.h
char* freerdp_get_status_name(int status){
    char* exit_name = NULL;
    switch (status) {
        //未完善处理，待测
        /* section 0-15: protocol-independent codes */
        case 0:   exit_name = "XF_EXIT_SUCCESS"; break;
        case 1:   exit_name = "XF_EXIT_DISCONNECT"; break;
        case 2:   exit_name = "XF_EXIT_LOGOFF"; break;
        case 3:   exit_name = "XF_EXIT_IDLE_TIMEOUT"; break;
        case 4:   exit_name = "XF_EXIT_LOGON_TIMEOUT"; break;
        case 5:   exit_name = "XF_EXIT_CONN_REPLACED";
        case 6:   exit_name = "XF_EXIT_OUT_OF_MEMORY"; break;
        case 7:   exit_name = "XF_EXIT_CONN_DENIED"; break;
        case 8:   exit_name = "XF_EXIT_CONN_DENIED_FIPS"; break;
        case 9:   exit_name = "XF_EXIT_USER_PRIVILEGES"; break;
        case 10:  exit_name = "XF_EXIT_FRESH_CREDENTIALS_REQUIRED"; break;
        case 11:  exit_name = "XF_EXIT_DISCONNECT_BY_USER"; break;

        //此段暂时未做处理，等待测试情况完善
        /* section 16-31: license error set */
        case 16:  exit_name = "XF_EXIT_LICENSE_INTERNAL"; break;
        case 17:  exit_name = "XF_EXIT_LICENSE_NO_LICENSE_SERVER"; break;
        case 18:  exit_name = "XF_EXIT_LICENSE_NO_LICENSE"; break;
        case 19:  exit_name = "XF_EXIT_LICENSE_BAD_CLIENT_MSG"; break;
        case 20:  exit_name = "XF_EXIT_LICENSE_HWID_DOESNT_MATCH"; break;
        case 21:  exit_name = "XF_EXIT_LICENSE_BAD_CLIENT"; break;
        case 22:  exit_name = "XF_EXIT_LICENSE_CANT_FINISH_PROTOCOL"; break;
        case 23:  exit_name = "XF_EXIT_LICENSE_CLIENT_ENDED_PROTOCOL"; break;
        case 24:  exit_name = "XF_EXIT_LICENSE_BAD_CLIENT_ENCRYPTION"; break;
        case 25:  exit_name = "XF_EXIT_LICENSE_CANT_UPGRADE"; break;
        case 26:  exit_name = "XF_EXIT_LICENSE_NO_REMOTE_CONNECTIONS"; break;
        //以下两段视为连接失败
        /* section 32-127: RDP protocol error set */
        case 32:   exit_name = "XF_EXIT_RDP"; break;  //8192
        /* section 128-254: xfreerdp specific exit codes */
        case 127:  exit_name = "XF_EXIT_VERYSTREAM_NOT_FOUNT";break;
        case 128:  exit_name = "XF_EXIT_PARSE_ARGUMENTS";break;
        case 129:  exit_name = "XF_EXIT_MEMORY";break;
        case 130:  exit_name = "XF_EXIT_PROTOCOL";break;
        case 131:  exit_name = "XF_EXIT_CONN_FAILED"; break;//33536  虚拟机端口有误或者网关密码不对
        case 132:  exit_name = "XF_EXIT_AUTH_FAILURE";break;
        case 133:  exit_name = "XF_EXIT_NEGO_FAILURE"; break;//34048 网络出错
        case 243 : exit_name = "XF_EXIT_CTRL_SHIFT_E";break;
        case 254:  exit_name = "XF_EXIT_RESTART";break;
        case 255:  exit_name = "XF_EXIT_UNKNOWN"; break;

        //此处的退出码是linux表里面没有的，不过可以在vcd-error.h里面找到，可以自己到里面查询，
        //目前发现有一个0xc是虚拟机注销返回的，未做处理，查询时可以自行根据0xc查询也可以加上class_type
        //即0x2000c之后使用freerdp_get_last_error_name和windows一样进行查询
        default:
            exit_name = "exit case default";
    }
    return exit_name;
}

char* freerdp_get_status_string(int status){
    char* message = NULL;
    switch (status) {
        case 5:  message = "有其他用户登录"; break;
        case 127: message = "verystream未安装"; break;
        case 133: message = "verystream连接失败！"; break;
        //case 253: message = "exit by Ctrl+Shift+e "; break;
    }
    return message;
}

int freerdp_get_status_reconnect_status(int status){
    if(status == 254)
        return 1;
    else
        return 0;
}
#endif




#endif
